<?php
    class Upload_crop
    {
        /**
         * 图片上传验证key
         */
        public $uploadKey = '5#2XXVXXSTILMC5';
        /**
         * 图片裁切验证key
         */
        public $cropKey = '694JRIXSLAP#*82';
        /**
         * 图片确认验证key
         */
        public $sureKey = '80#@EOPIYJFIAZC';
        /**
         * 文件上传网站的根目录
         */
        public $wwwroot = null;
        /**
         * 相对根目录的最终存放路径
         */
        public $dstroot = null;
        /**
         * 相对根目录的临时存放路径
         */
        public $tmproot = null;
        /**
         * 限制图片数组
         */
        public $imagelimit = array(
            'jpg',
            'JPG',
            'jpeg',
            'JPEG',
            'gif',
            'GIF',
            'png',
            'PNG'
        );

        /**
         * 书目库单个文件夹数量限制
         */
        public $positionInfo = 'current_position.txt';
        /**
         * 单个文件夹可以存放的最多图片数量
         */
        public $limit = '5000';

        function __construct($_args = null)
        {
            if (!empty($_args)) {
                foreach ($_args as $k => $v) {
                    $this->$k = $v;
                }
            }
            header('Content-type:text/html;Charset=UTF-8');
        }

        /**
         * 上传图片
         * @param $_data $_POST
         * @param int $_maxsize 上传限制大小 默认2M
         * @param string $_input_name file控件name属性值
         *
         * @return string 序列化后的上传图片信息
         */
        function upload($_maxsize = 2, $_input_name = 'mypic')
        {
            //这种情况是点了取消之后
            if (empty($_FILES)) {
                exit;
            }
            $picname = $_FILES [$_input_name] ['name'];
            $picsize = $_FILES [$_input_name] ['size'];
            $destination = '';
            $width = 0;
            $height = 0;
            if (!empty($picname)) {
                if ($picsize > $_maxsize * 1024 * 1024) {
                    exit ('图片大小不能超过' . $_maxsize . 'M');
                }
                $ext = strtolower($this->get_ext($picname));
                if (!in_array($ext, $this->imagelimit)) {
                    exit ('只能上传' . join('、', $this->imagelimit) . '格式的图片！');
                }
                $file_name = date('YmdHis') . rand(100, 999) . '_s.' . $ext;
                $destination = $this->tmproot . '/' . $file_name; // 新临时文件相对路径
                // 新临时文件上传路径
                $upload_pic_path = $this->wwwroot . '/' . $destination;
                // 生成新临时文件的路径,如果不存在的话
                $this->create_folder(dirname($upload_pic_path));
                // 开始上传图片
                $res = move_uploaded_file($_FILES [$_input_name] ['tmp_name'], $upload_pic_path);
                if ($res) {
                    // 删除上一次上传和裁切的图片
                    $this->del();
                }

                list($width, $height) = getimagesize($upload_pic_path);
            }
            $size = round($picsize / 1024, 2);

            return json_encode(array(
                'name' => $picname,
                'pic' => $destination,
                'token' => md5($destination . '_' . $this->uploadKey),
                'size' => $size,
                'w' => $width,
                'h' => $height
            ));
        }

        /**
         * 删除图片
         * @param $_data $_POST
         */
        function del($_filename = null)
        {

            $id = isset($_POST['id']) ? $_POST['id'] : false;

            //前一次上传图片路径
            $last_img = empty($_POST['last_img']) ? '' : $this->wwwroot . '/' . $_POST['last_img'];
            //前一次上传后裁切的图片路径
            $last_crop_img = empty($_POST['last_crop_img']) ? '' : $this->wwwroot . '/' . $_POST['last_crop_img'];
            $res = true;
            if (file_exists($last_img)) {
                $res &= unlink($last_img);
            }
            if (file_exists($last_crop_img)) {
                //这种情况就是点击确定之后
                if (isset($_filename) && $id) {
                    $pattern = '/^(.*)(' . str_replace('/', '\/', $this->tmproot) . ')(\/)(\d+_d)(\.\w+)$/';
                    $replacement = '$1' . $this->dstroot . '${3}' . $_filename . '$5';
                    $dst_crop_img = preg_replace($pattern, $replacement, $_POST['last_crop_img']);
                    $dst_crop_img_path = $this->wwwroot . '/' . $dst_crop_img;
                    $this->create_folder(dirname($dst_crop_img_path));
                    @rename($last_crop_img, $dst_crop_img_path); //将裁切后的文件定义为源文件,因为你点了确定
                    return json_encode(array(
                        'img' => $dst_crop_img,
                        'token' => md5($dst_crop_img . '_' . $this->sureKey)
                    ));
                } else {
                    $res &= unlink($last_crop_img);
                }
            } else {
                //传过来原图但不传裁切过的说明要留着裁切的图之后处理
                $pattern = '/^(.*\/\d+)(_s)(\.\w+)$/';
                $replacement = '$1_d$3';
                $dst_crop_img = preg_replace($pattern, $replacement, $_POST['last_img']);
                @rename($this->wwwroot . '/' . $dst_crop_img, $this->wwwroot . '/' . $_POST['last_img']);

                //返回重命名后的图片地址,裁切过的变原图
                return json_encode(array(
                    'img' => $_POST['last_img'],
                    'token' => md5($_POST['last_img'] . '_' . $this->sureKey)
                ));
            }

            return $res;
        }

        /**
         * 裁切图片
         */
        function crop()
        {
            //验证区 开始
            $echo = array(
                'code' => '1'
            );
            if (empty($_POST ["last_img"])) {
                //last_img不能为空
                $echo['code'] = 'null_last_img';
                exit(json_encode($echo));
            }
            if (empty($_POST['last_img_token'])) {
                //last_img验证串不能为空
                $echo['code'] = 'null_last_img_token';
                exit(json_encode($echo));
            }
            if ($_POST['last_img_token'] != md5($_POST["last_img"] . '_' . $this->uploadKey)) {
                //验证失败
                $echo['code'] = 'danger_last_img';
                exit(json_encode($echo));
            }
            $src_image_path = $this->wwwroot . '/' . $_POST["last_img"];
            if (!file_exists($src_image_path)) {
                //文件不存在
                $echo['code'] = 'error_last_img';
                exit(json_encode($echo));
            }
            //验证区 结束
            $pWidth = $_POST ["imageW"];
            $pHeight = $_POST ["imageH"];
            $ext = $this->get_ext($_POST ["last_img"]); //后缀名
            $function = $this->return_correct_function($ext);
            $image = $function ($src_image_path);
            $width = imagesx($image);
            $height = imagesy($image);
            // Resample
            $image_p = imagecreatetruecolor($pWidth, $pHeight);
            $this->set_transparency($image, $image_p, $ext);
            imagecopyresampled($image_p, $image, 0, 0, 0, 0, $pWidth, $pHeight, $width, $height);
            imagedestroy($image);
            $widthR = imagesx($image_p);
            $hegihtR = imagesy($image_p);

            $selectorX = $_POST ["selectorX"];
            $selectorY = $_POST ["selectorY"];

            if ($_POST ["imageRotate"]) {
                $angle = 360 - $_POST ["imageRotate"];
                $image_p = imagerotate($image_p, $angle, 0);

                $pWidth = imagesx($image_p);
                $pHeight = imagesy($image_p);

                $diffW = abs($pWidth - $widthR) / 2;
                $diffH = abs($pHeight - $hegihtR) / 2;

                $_POST ["imageX"] = ($pWidth > $widthR ? $_POST ["imageX"] - $diffW : $_POST ["imageX"] + $diffW);
                $_POST ["imageY"] = ($pHeight > $hegihtR ? $_POST ["imageY"] - $diffH : $_POST ["imageY"] + $diffH);
            }

            $dst_x = $src_x = $dst_y = $src_y = 0;

            if ($_POST ["imageX"] > 0) {
                $dst_x = abs($_POST ["imageX"]);
            } else {
                $src_x = abs($_POST ["imageX"]);
            }
            if ($_POST ["imageY"] > 0) {
                $dst_y = abs($_POST ["imageY"]);
            } else {
                $src_y = abs($_POST ["imageY"]);
            }

            $viewport = imagecreatetruecolor($_POST ["viewPortW"], $_POST ["viewPortH"]);
            $white = imagecolorallocate($viewport, 255, 255, 255);
            imagefill($viewport, 0, 0, $white);
            $this->set_transparency($image_p, $viewport, $ext);

            imagecopy($viewport, $image_p, $dst_x, $dst_y, $src_x, $src_y, $pWidth, $pHeight);
            imagedestroy($image_p);

            $selector = imagecreatetruecolor($_POST ["selectorW"], $_POST ["selectorH"]);
            $this->set_transparency($viewport, $selector, $ext);
            imagecopy($selector, $viewport, 0, 0, $selectorX, $selectorY, $_POST ["viewPortW"], $_POST ["viewPortH"]);
            //裁剪之后的图片和原图放在同一个文件夹
            $destination = preg_replace('/^(.*\d+)(_s)(\.\w+)$/', '$1_d$3', $_POST['last_img']); // 裁切后新文件名称_s变_d

            // 裁切后的上传路径
            $upload_pic_path = $this->wwwroot . '/' . $destination;
            $this->parse_image($ext, $selector, $upload_pic_path);
            imagedestroy($viewport);

            // 返回裁切后的图片相对路径
            $echo['data'] = array(
                'last_crop_img' => $destination,
                'token' => md5($destination . '_' . $this->cropKey)
            );
            echo json_encode($echo);
        }


        /**
         * 创建多级目录
         */
        function create_folder($_path)
        {
            if (!file_exists($_path)) {
                $this->create_folder(dirname($_path));
                mkdir($_path, 0777);
            }
        }

        /**
         * 获取文件扩展名
         */
        function get_ext($_fileName)
        {
            $tmpArr = explode('.', $_fileName);

            return end($tmpArr);
        }

        /**
         * 算出指定年份,指定月份的天数
         *
         * @param Int $_y
         * @param Int $_m
         *
         * @return Int
         */
        function month_n_day($_y, $_m)
        {
            $monthDay = array(
                31,
                28,
                31,
                30,
                31,
                30,
                31,
                31,
                30,
                31,
                30,
                31
            );
            if (2 == $_m) {
                return ((($_y % 4 == 0) && ($_y % 100 != 0) || ($_y % 400 == 0)) ? 29 : 28);
            } else {
                return $monthDay [$_m - 1];
            }
        }

        function determineImageScale($sourceWidth, $sourceHeight, $targetWidth, $targetHeight)
        {
            $scalex = $targetWidth / $sourceWidth;
            $scaley = $targetHeight / $sourceHeight;

            return min($scalex, $scaley);
        }

        /**
         * 根据图片扩展名返回相应的创建图像资源的函数
         */
        function return_correct_function($_ext)
        {
            $function = "";
            switch ($_ext) {
                case "png" :
                    $function = "imagecreatefrompng";
                    break;
                case "jpeg" :
                    $function = "imagecreatefromjpeg";
                    break;
                case "jpg" :
                    $function = "imagecreatefromjpeg";
                    break;
                case "gif" :
                    $function = "imagecreatefromgif";
                case "PNG" :
                    $function = "imagecreatefrompng";
                    break;
                case "JPEG" :
                    $function = "imagecreatefromjpeg";
                    break;
                case "JPG" :
                    $function = "imagecreatefromjpeg";
                    break;
                case "GIF" :
                    $function = "imagecreatefromgif";
                    break;
            }

            return $function;
        }

        /**
         * 粘贴图像资源到文件
         */
        function parse_image($ext, $img, $file = null)
        {
            switch ($ext) {
                case "png" :
                    imagepng($img, ($file != null ? $file : ''));
                    break;
                case "jpeg" :
                    imagejpeg($img, ($file ? $file : ''), 90);
                    break;
                case "jpg" :
                    imagejpeg($img, ($file ? $file : ''), 90);
                    break;
                case "gif" :
                    imagegif($img, ($file ? $file : ''));
                    break;
                case "PNG" :
                    imagepng($img, ($file != null ? $file : ''));
                    break;
                case "JPEG" :
                    imagejpeg($img, ($file ? $file : ''), 90);
                    break;
                case "JPG" :
                    imagejpeg($img, ($file ? $file : ''), 90);
                    break;
                case "GIF" :
                    imagegif($img, ($file ? $file : ''));
                    break;

            }
        }

        /**
         * 设置透明区域
         */
        function set_transparency($imgSrc, $imgDest, $ext)
        {
            if ($ext == "png" || $ext == "gif") {
                $trnprt_indx = imagecolortransparent($imgSrc);
                // If we have a specific transparent color
                if ($trnprt_indx >= 0) {
                    // Get the original image's transparent color's RGB values
                    $trnprt_color = imagecolorsforindex($imgSrc, $trnprt_indx);
                    // Allocate the same color in the new image resource
                    $trnprt_indx = imagecolorallocate($imgDest, $trnprt_color ['red'], $trnprt_color ['green'], $trnprt_color ['blue']);
                    // Completely fill the background of the new image with
                    // allocated
                    // color.
                    imagefill($imgDest, 0, 0, $trnprt_indx);
                    // Set the background color for new image to transparent
                    imagecolortransparent($imgDest, $trnprt_indx);
                } // Always make a transparent background color for PNGs that don't
                // have
                // one allocated already
                elseif ($ext == "png") {
                    // Turn off transparency blending (temporarily)
                    imagealphablending($imgDest, true);
                    // Create a new transparent color for image
                    $color = imagecolorallocatealpha($imgDest, 0, 0, 0, 127);
                    // Completely fill the background of the new image with
                    // allocated
                    // color.
                    imagefill($imgDest, 0, 0, $color);
                    // Restore transparency blending
                    imagesavealpha($imgDest, true);
                }
            }
        }

        /**
         * 初始化临时文件夹
         * 如果图片已经超过今天文件夹的容量
         * 自动向明天的文件夹添加,跨月判断
         * 可能永远不会进入第2层递归(每天有超过5000+的图片录入?!)
         */
        function init_tmp_folder(&$_y, &$_m, &$_d, $_path)
        {
            $destination_tmp_folder = $_path . '/' . $_y . $this->pad($_m) . '/' . $this->pad($_d) . '/'; // 上传文件临时路径
            $realfileDir = $this->wwwroot . '/' . $destination_tmp_folder;
            if (!file_exists($realfileDir)) {
                $this->create_folder($realfileDir);
            } else {
                //空文件夹默认有[.][..]两个文件
                $currentCount = count(scandir($realfileDir));
                if (($currentCount - 2) >= $this->limit) {
                    if ($_d == $this->month_n_day($_y, $_m)) {
                        if (12 == $_m) {
                            $_y++;
                            $_m = 1;
                            $_d = 1;
                        } else {
                            $_m++;
                            $_d = 1;
                        }
                    } else {
                        $_d++;
                    }
                    file_put_contents($this->wwwroot . '/' . $_path . '/' . $this->positionInfo, $_y . $this->pad($_m) . $this->pad($_d));
                    $destination_tmp_folder = $this->init_tmp_folder($_y, $_m, $_d, $_path);
                }
            }

            return $destination_tmp_folder;
        }

        /**
         *
         * 左侧填充0
         * @param $_str
         *
         * @return string
         */
        function pad($_str)
        {
            return str_pad($_str, 2, '0', STR_PAD_LEFT);
        }

        /**
         * 获取一个不会重复的文件名
         * $_path 目标文件路径
         * $_head 文件名前半部分
         * $_tail 文件名后半部分需要随机的位数
         * $_ext 扩展名
         */
        function unique_file_name($_path, $_head, $_tail, $_ext)
        {
            $file = $_head . rand(str_pad(1, $_tail, 0), str_pad(9, $_tail, 9)) . '.' . $_ext;
            if (file_exists($_path . '/' . $file)) {
                return $this->unique_file_name($_path, $_head, $_tail, $_ext);
            } else {
                return $file;
            }
        }

    }